package com.twc.ftp.controllers;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.twc.ftp.config.BehindRunningCfg;
import com.twc.ftp.dto.DirDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by twc on 10:58 2024/4/19.
 */
@Controller
@RequestMapping("file")
public class FileController {

    @Value("${root.path}")
    private String rootPath;

    @Autowired
    private BehindRunningCfg behindRunningCfg;

    /**
     * 上传文件
     *
     * @param file
     * @param path
     * @return
     */
    @RequestMapping("upload")
    @ResponseBody
    public Map<String, String> upload(@RequestParam("file") MultipartFile file, @RequestParam("path") String path) {
        // 判断文件是否为空
        HashMap<String, String> message = new HashMap<>();
        if (!file.isEmpty()) {
            try {
                // 文件保存路径
                String filePath = rootPath + path + File.separator + file.getOriginalFilename();
                // 转存文件
                file.transferTo(new File(filePath));
                message.put("status", "ok");
            } catch (Exception e) {
                message.put("status", "error");
            }
        }
        return message;
    }


    /**
     * 下载
     *
     * @param response
     * @param path
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/download")
    public String downloads(HttpServletResponse response, @RequestParam("path") String path) throws Exception {
        String fileName = path.substring(path.lastIndexOf(File.separator) + 1);
        File file = new File(rootPath + path);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        FileInputStream input = new FileInputStream(file);
        OutputStream out = response.getOutputStream();
        byte[] buff = null;
        buff = new byte[1024];
        long size = FileUtil.size(file);
        if (size >= 1024 * 20) {
            buff = new byte[1024 * 10];
        }
        if (size < 1024 * 20) {
            buff = new byte[(int) size];
        }
        if (size == 0) {
            buff = new byte[50];
        }

        int index = 0;
        while ((index = input.read(buff)) != -1) {
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }


    /**
     * 得到系统根路径磁盘列表
     *
     * @return
     */
    @RequestMapping("getRootFileList")
    @ResponseBody
    public HashMap getRootFileList() {
        HashMap<String, Object> rs = new HashMap<>();
        if (StrUtil.isNotBlank(rootPath)) {
            return getFileList("");
        }
        rs.put("status", "error");
        return rs;
    }


    /**
     * 得到一个目录下的文件列表
     *
     * @param path
     * @return
     */
    @RequestMapping("getFileList")
    @ResponseBody
    public HashMap getFileList(@RequestParam("path") String path) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String absolutePath = rootPath + path;
        HashMap<String, Object> rs = new HashMap<>();
        FileSystemView sys = FileSystemView.getFileSystemView();
        File root = FileUtil.file(absolutePath);
        File[] files = root.listFiles();

        List<DirDTO> list = new ArrayList<>();
        if(files != null){
            List<DirDTO> listDir = new ArrayList<>();
            List<DirDTO> listFile = new ArrayList<>();
            for (File file : files) {
                DirDTO d = new DirDTO();
                if(path.equals("")){
                    d.setPath(file.getName());
                }else{
                    d.setPath(path + File.separator + file.getName());
                }
                if(file.isDirectory()){
                    d.setIcon("dir.svg");
                }else{
                    String type = behindRunningCfg.findByFileType(file.getName());
                    if(type == null){
                        d.setIcon("file.svg");
                    } else{
                        d.setIcon(type + ".svg");
                    }
                }
                d.setSimpleName(file.getName());
                d.setLastModified(format.format(new Date(file.lastModified())));
                d.setType(file.isDirectory() ? "dir" : "file");
                d.setInfo(sys.getSystemTypeDescription(file));
                if (!FileUtil.isDirectory(file)) {
                    String readableSize = FileUtil.readableFileSize(file);
                    if ("0".equals(readableSize) || "".equals(readableSize)) {
                        d.setReadableSize("-");
                    } else {
                        d.setReadableSize(readableSize);
                    }
                } else {
                    d.setReadableSize("-");
                }
                if (file.isDirectory()) {
                    listDir.add(d);
                } else {
                    listFile.add(d);
                }
            }
            listDir = listDir.stream().sorted(Comparator.comparing(DirDTO::getSimpleName)).collect(Collectors.toList());
            listFile = listFile.stream().sorted(Comparator.comparing(DirDTO::getSimpleName)).collect(Collectors.toList());

            list.addAll(listDir);
            list.addAll(listFile);
        }

        rs.put("absolutePath", absolutePath);
        rs.put("relativePath", path);
        if(path.contains(File.separator)){
            rs.put("backPath", path.substring(0, path.lastIndexOf(File.separator)));
        }else{
            rs.put("backPath", "");
        }
        rs.put("status", "ok");
        rs.put("rs", list);
        return rs;
    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     */
    @RequestMapping("delFile")
    @ResponseBody
    public HashMap delFile(@RequestParam("path") String path) {
        HashMap<String, Object> rs = new HashMap<>();
        Console.log("删除文件：" + rootPath + path);
        FileUtil.del(rootPath + path);
        return rs;
    }

    /**
     * 压缩文件或文件夹
     *
     * @param path
     * @return
     */
    @RequestMapping("package")
    @ResponseBody
    public HashMap packagePath(@RequestParam("path") String path) {
        HashMap<String, Object> rs = new HashMap<>();
        ZipUtil.zip(path);
        rs.put("status", "ok");
        return rs;
    }


    /**
     * 解压缩文件或文件夹
     *
     * @param path
     * @return
     */
    @RequestMapping("unPackage")
    @ResponseBody
    public HashMap unPackage(@RequestParam("path") String path) {
        HashMap<String, Object> rs = new HashMap<>();
        if (path.contains(".zip")) {
            ZipUtil.unzip(path);
        }
        rs.put("status", "ok");
        return rs;
    }

    /**
     * 新建文件夹
     *
     * @param path
     * @return
     */
    @RequestMapping("newPackage")
    @ResponseBody
    public HashMap newPackage(@RequestParam("path") String path, @RequestParam("name") String name) {
        HashMap<String, Object> rs = new HashMap<>();
        if(!path.equals("")){
            path = path + File.separator;
        }
        FileUtil.mkdir(rootPath + path + name);
        rs.put("status", "ok");
        return rs;
    }


    /**
     * 删除文件夹
     *
     * @param path
     * @return
     */
    @RequestMapping("delDir")
    @ResponseBody
    public HashMap delDir(@RequestParam("path") String path) {
        HashMap<String, Object> rs = new HashMap<>();
        Console.log("删除目录：" + rootPath + path);
        FileUtil.del(rootPath + path);
        rs.put("status", "ok");
        return rs;
    }


    /**
     * 复制整个文件和文件夹
     *
     * @param oldPath
     * @param newPath
     * @return
     */
    @ResponseBody
    @RequestMapping("copyFileOrDir")
    public HashMap<String, Object> copyFileOrDir(@RequestParam("oldPath") String oldPath, @RequestParam("newPath") String newPath) {
        HashMap<String, Object> rs = new HashMap<>();
        FileUtil.copy(oldPath, newPath, true);
        rs.put("status", "ok");
        return rs;
    }

    /**
     * 移动整个文件和文件夹
     *
     * @param oldPath
     * @param newPath
     * @return
     */
    @ResponseBody
    @RequestMapping("rmFileOrDir")
    public HashMap<String, Object> rmFileOrDir(@RequestParam("oldPath") String oldPath, @RequestParam("newPath") String newPath) {
        HashMap<String, Object> rs = new HashMap<>();
        FileUtil.copy(oldPath, newPath, true);
        FileUtil.del(oldPath);
        rs.put("status", "ok");
        return rs;
    }


    /**
     * 修改文件名或目录名
     *
     * @param path
     * @param newName
     * @return
     */
    @ResponseBody
    @RequestMapping("renameFileOrDir")
    public HashMap<String, Object> renameFileOrDir(@RequestParam("path") String path, @RequestParam("newName") String newName) {
        HashMap<String, Object> rs = new HashMap<>();
        FileUtil.rename(FileUtil.file(path), newName, false, true);
        rs.put("status", "ok");
        return rs;
    }

}
